package com.yuzhenxin.coursesystem.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.framework.common.exception.ServiceException;
import com.example.framework.security.core.dto.JwtTokenRespDto;
import com.example.framework.security.core.util.JwtTokenUtils;
import com.example.framework.security.core.util.SecurityFrameworkUtils;
import com.yuzhenxin.coursesystem.config.enums.Constants;
import com.yuzhenxin.coursesystem.config.enums.ErrorCodeConstants;
import com.yuzhenxin.coursesystem.controller.admin.vo.UserLoginReqVO;
import com.yuzhenxin.coursesystem.controller.admin.vo.UserPasswordUpdateReqVO;
import com.yuzhenxin.coursesystem.dto.UserInfoDTO;
import com.yuzhenxin.coursesystem.entity.StudentDO;
import com.yuzhenxin.coursesystem.entity.TeacherDO;
import com.yuzhenxin.coursesystem.mapper.StudentMapper;
import com.yuzhenxin.coursesystem.mapper.TeacherMapper;
import com.yuzhenxin.coursesystem.service.AdminService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Slf4j
@Service
public class AdminServiceImpl implements AdminService {

    @Resource
    private PasswordEncoder passwordEncoder;

    @Resource
    private StudentMapper studentMapper;

    @Resource
    private TeacherMapper teacherMapper;

    @Resource
    private JwtTokenUtils jwtTokenUtils;

    @Override
    public JwtTokenRespDto login(UserLoginReqVO reqDTO) {
        Integer userId = reqDTO.getNumber();
        String password = reqDTO.getPassword();

        UserInfoDTO userInfoDTO = new UserInfoDTO();
        userInfoDTO.setUsername(String.valueOf(userId));
        userInfoDTO.setType(reqDTO.getType());
        Integer userType = reqDTO.getType();
        if (Objects.equals(userType, Constants.STUDENT)) {
            LambdaQueryWrapper<StudentDO> queryWrapper = Wrappers.<StudentDO>lambdaQuery()
                    .eq(StudentDO::getNumber, userId);
            StudentDO studentEntity = studentMapper.selectOne(queryWrapper);
            Assert.notNull(studentEntity, () -> ServiceException.of(ErrorCodeConstants.LOGIN_ERROR));
            // 加密后比较
            if (!passwordEncoder.matches(password, studentEntity.getPassword())) {
                throw ServiceException.of(ErrorCodeConstants.LOGIN_ERROR);
            }
            BeanUtils.copyProperties(studentEntity, userInfoDTO);
        } else if (Objects.equals(userType, Constants.TEACHER)) {
            TeacherDO teacherEntity = teacherMapper.selectOne(Wrappers.<TeacherDO>lambdaQuery()
                    .eq(TeacherDO::getNumber, userId));
            Assert.notNull(teacherEntity, () -> ServiceException.of(ErrorCodeConstants.LOGIN_ERROR));
            if (!passwordEncoder.matches(password, teacherEntity.getPassword())) {
                log.error("教师登录密码错误");
                throw ServiceException.of(ErrorCodeConstants.LOGIN_ERROR);
            }
            BeanUtils.copyProperties(teacherEntity, userInfoDTO);
        } else {
            throw ServiceException.of(ErrorCodeConstants.INVALID_USER_TYPE);
        }

        JwtTokenRespDto jwtTokenRespDto = jwtTokenUtils.generateTokenAndRefreshToken(userInfoDTO);
        log.debug("生成jwt token，userId: {}, userInfo: {}", userId, userInfoDTO);
        return jwtTokenRespDto;
    }

    @Override
    public void updatePassword(UserPasswordUpdateReqVO reqDto) {
        // 登录了才能修改密码
        String userId = SecurityFrameworkUtils.getLoginUserId();

        Integer userType = reqDto.getType();
        if (Objects.equals(userType, Constants.STUDENT)) {
            LambdaQueryWrapper<StudentDO> queryWrapper = Wrappers.<StudentDO>lambdaQuery()
                    .eq(StudentDO::getNumber, userId)
                    .eq(StudentDO::getPassword, reqDto.getOriginPassword());
            StudentDO studentEntity = studentMapper.selectOne(queryWrapper);
            if (Objects.isNull(studentEntity) || !passwordEncoder.matches(reqDto.getOriginPassword(), studentEntity.getPassword())) {
                throw ServiceException.of(ErrorCodeConstants.OLD_PASSWORD_ERROR);
            }

            studentEntity.setPassword(passwordEncoder.encode(reqDto.getNewPassword()));
            if (studentMapper.updateById(studentEntity) == 0) {
                log.warn("学生修改的新旧密码一致");
            }
        } else if (Objects.equals(userType, Constants.TEACHER)) {
            LambdaQueryWrapper<TeacherDO> queryWrapper = Wrappers.<TeacherDO>lambdaQuery()
                    .eq(TeacherDO::getNumber, userId)
                    .eq(TeacherDO::getPassword, reqDto.getOriginPassword());
            TeacherDO teacherEntity = teacherMapper.selectOne(queryWrapper);
            if (Objects.isNull(teacherEntity) || !passwordEncoder.matches(reqDto.getOriginPassword(), teacherEntity.getPassword())) {
                throw ServiceException.of(ErrorCodeConstants.OLD_PASSWORD_ERROR);
            }

            teacherEntity.setPassword(passwordEncoder.encode(reqDto.getNewPassword()));
            if (teacherMapper.updateById(teacherEntity) == 0) {
                log.warn("教师修改的新旧密码一致");
            }
        } else {
            throw ServiceException.of(ErrorCodeConstants.INVALID_USER_TYPE);
        }
    }
}
